﻿#ifndef _EXPORT_H
#define _EXPORT_H

#include <string>
using namespace std;

template<typename T, typename TBase>
class IsDerived
{
public:
	static int aux(TBase* base);

	static char aux(void* other);

	enum
	{
		RESULT = (sizeof(int) == sizeof(aux((T*)NULL))),
	};
};

//静态select
template<bool, typename T1, typename T2>
struct Select
{
    typename T1 TYPE;
};

template<typename T1, typename T2>
struct Select<false, T1, T2>
{
    typename T2 TYPE;
};

//检测类型是否为引用类型
template<typename T>
struct IsRefType
{
    enum {value = false};
    typedef T REMOVE_REF_TYPE ;
};

template<typename T>
struct IsRefType<T&>
{
    enum {value = true};
    typedef T REMOVE_REF_TYPE ;
};

//检测类型是否为指针类型
template<typename T>
struct IsPtrType
{
    enum {value = false};
    typedef T REMOVE_PTR_TYPE ;
};
template<typename T>
struct IsPtrType<T*>
{
    enum {value = true};
    typedef T REMOVE_PTR_TYPE ;
};

//获取类型的原始类型
template<typename T>
struct BaseType
{
    typedef T BASETYPE;
};

template<typename T>
struct BaseType<T&>
{
    //递归
    typedef typename BaseType<T>::BASETYPE BASETYPE;
};

template<typename T>
struct BaseType<T*>
{
    //递归
    typedef typename BaseType<T>::BASETYPE BASETYPE;
};

//判断两个类型是否同类型
template<typename T1, typename T2>
struct IsSameType
{
    enum {value = false};
};
template<typename T1>
struct IsSameType<T1,T1>
{
    enum {value = true};
};

#define CLASS_HEAD_LEN 6

class TemplateFunc
{
public:
    //获取类型T的原始类型的字符串输出
    template<typename T>
    static string GetBaseTypeName()
    {
        typedef BaseType<T>::BASETYPE BASETYPE;

        string classname = typeid(BASETYPE).name();
        size_t ret = classname.find(' ');
        if((int)ret > 0)
        {
            return classname.substr(CLASS_HEAD_LEN, classname.size() - CLASS_HEAD_LEN);
        }
        else
        {
            return classname;
        }
    }

    template<>
    static string GetBaseTypeName<string>()
    {
        return "string";
    }

    template<>
    static string GetBaseTypeName<void>()
    {
        return "void";
    }

    //以下模板函数作为AngelScript导出时使用
    template<typename T>
    static string GetBaseTypeName4AL()
    {
        typedef BaseType<T>::BASETYPE BASETYPE;

        string classname = typeid(BASETYPE).name();
        size_t ret = classname.find(' ');
        if((int)ret > 0)
        {
            return classname.substr(CLASS_HEAD_LEN, classname.size() - CLASS_HEAD_LEN) + " &";
        }
        else
        {
            return classname;
        }
    }

    template<>
    static string GetBaseTypeName4AL<string>()
    {
        return "string &";
    }

    template<>
    static string GetBaseTypeName4AL<void>()
    {
        return "void";
    }
public:
    //获取一个类型的完整字符串输出
    //因此:int*和int**不一样
    template<typename T>
    static string GetCompleteTypeName()
    {
        bool isref = IsRefType<T>::value;
        typedef IsRefType<T>::REMOVE_REF_TYPE REMOVE_REF_TYPE;

        bool isptr = IsPtrType<REMOVE_REF_TYPE>::value;
        typedef IsPtrType<REMOVE_REF_TYPE>::REMOVE_PTR_TYPE REMOVE_PTR_TYPE;

        string retstr;

        if(IsPtrType<REMOVE_PTR_TYPE>::value)
        {
            retstr += GetCompleteTypeName<REMOVE_PTR_TYPE>();
        }
        else
        {
            retstr += GetBaseTypeName4AL<BaseType<T>::BASETYPE>();
        }

        if(isptr)
        {
            retstr += "*";
        }

        if(isref)
        {
            retstr += " &";
        }

        return retstr;
    }

    template<typename T>
    static string GetFuncDeclarationString4AL(T t, const char* funcname)
    {
        static char err[0];
        return "default";
    }

    template<typename RETTYPE>
    static string GetFuncDeclarationString4AL(RETTYPE (*p)(void), const char* funcname)
    {
        return GetBaseTypeName4AL<BaseType<RETTYPE>::BASETYPE>() + " " + funcname + "()";
    }

    template<typename RETTYPE, typename ARG1>
    static string GetFuncDeclarationString4AL(RETTYPE (*p)(ARG1), const char* funcname)
    {
        return GetBaseTypeName4AL<BaseType<RETTYPE>::BASETYPE>() + " " + funcname + "(" + GetBaseTypeName4AL<BaseType<ARG1>::BASETYPE>() + ")";
    }

    template<typename RETTYPE, typename ARG1, typename ARG2>
    static string GetFuncDeclarationString4AL(RETTYPE (*p)(ARG1, ARG2), const char* funcname)
    {
        return GetBaseTypeName4AL<BaseType<RETTYPE>::BASETYPE>() + " " + funcname + "(" + GetBaseTypeName4AL<BaseType<ARG1>::BASETYPE>() + "," + GetBaseTypeName4AL<BaseType<ARG2>::BASETYPE>() + ")";
    }

    template<typename RETTYPE, typename ARG1, typename ARG2, typename ARG3>
    static string GetFuncDeclarationString4AL(RETTYPE (*p)(ARG1, ARG2, ARG3), const char* funcname)
    {
        return GetBaseTypeName4AL<BaseType<RETTYPE>::BASETYPE>() + " " + funcname + "(" + GetBaseTypeName4AL<BaseType<ARG1>::BASETYPE>() + "," + GetBaseTypeName4AL<BaseType<ARG2>::BASETYPE>() + ", " + GetBaseTypeName4AL<BaseType<ARG3>::BASETYPE>() + ")";
    }

protected:

};

#endif
